<template>
  <div class="render-target-prc">
    <!-- threejs官网的 ‘一些有用的链接’-render-target -->
    <div class="canvas" ref="canvas"></div>
  </div>
</template>

<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const rtScene = new THREE.Scene();
rtScene.background = new THREE.Color('red');
const rtWidth = 512;
const rtHeight = 512;
const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);
const rtCamera = new THREE.PerspectiveCamera(75, rtWidth / rtHeight, 0.1, 5);
rtCamera.position.z = 2;
{
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(-1, 2, 4);
  rtScene.add(light);
}

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 5);
camera.position.z = 2;
{
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(-1, 2, 4);
  scene.add(light);
}
const renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true,
});
renderer.debug.checkShaderErrors = false;
renderer.setClearColor(new THREE.Color(), 0);
renderer.setPixelRatio(750 / window.innerWidth);
@Options({ components: {} })
export default class RenderTargetPrc extends Vue {
  public rect: DOMRect|null = null;

  public resizeRendererToDisplaySize(renderer: THREE.WebGLRenderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needSize = canvas.width !== width || canvas.height !== height;
    if (needSize) {
      renderer.setSize(width, height, false);
    }
    return needSize;
  }
  public makeInstance(geometry: THREE.BoxGeometry, color: number, x: number) {
    const material = new THREE.MeshPhongMaterial({ color });
    const cube = new THREE.Mesh(geometry, material);
    rtScene.add(cube);
    cube.position.x = x;
    return cube;
  }
  public mounted() {
    this.rect = (this.$el as HTMLElement).getBoundingClientRect();
    renderer.setSize(this.rect.width, this.rect.height, false);
    (this.$refs.canvas as HTMLDivElement).append(renderer.domElement);

    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const rtCubes = [
      this.makeInstance(geometry, 0x44aa88, 0),
      this.makeInstance(geometry, 0x8844aa, -2),
      this.makeInstance(geometry, 0xaa8844, 2),
    ];
    const material = new THREE.MeshPhongMaterial({
      map: renderTarget.texture,
    });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);


    renderer.setAnimationLoop((time) => {
      // eslint-disable-next-line no-param-reassign
      time *= 0.001;
      if (this.resizeRendererToDisplaySize(renderer)) {
        const canvas = renderer.domElement;
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();
      }
      rtCubes.forEach((cube, index) => {
        const speed = 1 + index * .1;
        const rot = time * speed;
        cube.rotation.x = rot;
        cube.rotation.y = rot;
      });

      renderer.setRenderTarget(renderTarget);
      renderer.render(rtScene, rtCamera);
      renderer.setRenderTarget(null);

      cube.rotation.x = time;
      cube.rotation.y = time * 1.1;

      renderer.render(scene, camera);
    });

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableZoom = false;
  }
}
</script>

<style lang="postcss" scoped>
  .render-target-prc{
    touch-action: none;
    position: absolute;
    left: 0;top: 0;
    width: 100%;height: 100%;
    background: #98bbd1;
    .canvas{
      position: absolute;
      left: 0;top: 0;
      width: 100%;height: 100%;
       :deep(canvas){
        width: 100%;height: 100%;
      }
    }
  }
</style>
